#include <iostream>
#include <thread>
#include <chrono>

//c
#include <unistd.h>
#include <sys/socket.h>
#include <sys/fcntl.h>
#include <arpa/inet.h>

int main() {
    /*    server                      |      client
        accept(block)                 |         
            ↓                       <---     connect
        read(nonblock, return -1)     |       
            ↓  (loop read)          <---      write
          read(return size)
            ↓
          do sth...
    */
    //https://mp.weixin.qq.com/s/YdIdoZ_yusVWza1PU7lWaw

    int socketfd = socket(AF_INET, SOCK_STREAM, 0);
    if (socketfd == -1)
        return -1;

    sockaddr_in addrServer;
    addrServer.sin_family = AF_INET;
    addrServer.sin_port = htons(SERT_PORT);
    inet_pton(AF_INET, "0.0.0.0", &addrServer.sin_addr);

    if (bind(socketfd, (sockaddr*)(&addrServer), sizeof(sockaddr_in)) == -1)
        return -1;

    if (listen(socketfd, 4) == -1)
        return -1;

    while (true) {
        sockaddr_in client;
        socklen_t len(sizeof(sockaddr_in));
        int acceptfd = accept(socketfd, (sockaddr*)(&client), &len);
        std::cout << "acceptfd: " << acceptfd << std::endl;

        if (acceptfd == -1)
            continue;

        //file control
        //fd, cmd... 对 fd 执行 cmd 操作

        //F_SETFL 设置文件状态
        //O_NONBLOCK 非阻塞线程
        if (fcntl(acceptfd, F_SETFL, O_NONBLOCK) == -1)
            continue;

        //开启一个线程任务用于异步 io
        std::thread t([acceptfd]() {
            char buf[MAXLINE + 1] = {0};
            while (read(acceptfd, buf, MAXLINE) == -1) {
                std::this_thread::sleep_for(std::chrono::milliseconds(500));
            }

            std::cout << buf << std::endl;
            write(acceptfd, buf, MAXLINE);  //echo
            close(acceptfd);
        });

        t.detach();
    }
    
    close(socketfd);
    return 0;
}